<template>
  <div class="upload-box">
    <!-- list-type:显示 上传按钮的样式 -->
    <!-- action：把图片上传到服务器对应域名的地址 （只支持post请求）
  1.如果把图片上传到自己的服务器中，可以使用action
  2.如果上传到第三方云服务，action一般赋值为 # 表示不使用action 上传
  -->
    <!-- :file-list: 配置默认图片 -->
    <!-- :on-preview: 可以预览大图 -->
    <!-- :limit: 最大允许上传个数-->
    <!-- :on-exceed: 文件超出个数限制时的钩子-->
    <!-- :on-remove 文件列表移除文件时的钩子 -->
    <!-- :http-request:覆盖默认的上传行为，可以自定义上传的实现 -->
    <!-- :on-change  文件状态改变时的钩子，添加文件、上传成功和上传失败时都会被调用-->
    <!-- :before-upload：  -->
    <el-upload
      list-type="picture-card"
      action="#"
      :file-list="filelist"
      :on-preview="handlePictureCardPreview"
      :class="{disabled: fileComputed }"
      :on-remove="handleRemove"
      :http-request="httpRequest"
      :on-change="handleChange"
      :before-upload="beforeUpload"
    >
      <i class="el-icon-plus" />
    </el-upload>
    <el-dialog :visible.sync="dialogVisible" title="图片预览" :close-on-click-modal="false">
      <img width="100%" :src="dialogImageUrl" alt="">
    </el-dialog>
  </div>

</template>

<script>
import cos from '@/utils/cos'
export default {
  name: 'ImageUpload',
  props: {
    // 使用组件时，传来的参数，控制允许上传的最大图片数量
    limit: {
      type: Number,
      default: 1
    }
  },
  data () {
    return {
      filelist: [],
      dialogVisible: false, // 控制预览弹框的显示隐藏
      dialogImageUrl: ''// 预览弹框里img标签的src地址
    }
  },
  computed: {
    // 根据filelist的数量 与传来的参数进行对比  返回布尔值，来控制是否添加这个disabled类名  来控制添加图片的显示隐藏
    fileComputed () {
      return this.filelist.length >= this.limit
    },
    // 根据上传图片的状态 来判断是否上传完成
    // 即使没有上传，也会返回true
    isAllUploadSuccess () {
      return this.filelist.every(item => item.status === 'success')
    }
  },
  methods: {
    /**
     *点击图片预览
     */
    handlePictureCardPreview (file) {
      this.dialogVisible = true
      this.dialogImageUrl = file.url
    },
    /**
     * 删除图片的钩子函数
     * file:已删除的图片信息
     * filelist:未删除的图片信息
     */
    handleRemove (file, filelist) {
      // 最好不直接赋值，因为是数组，直接赋值 地址一样 会相互影响
      // this.filelist = [...filelist]
    // 根据uid过滤出来跟已删除的图片不i一样的
      this.filelist = this.filelist.filter(item => item.uid !== file.uid)
    },
    /**
     *自定义上传
     */
    httpRequest ({ file }) {
      // 进行上传操作
      if (!file) return
      // 找到filelist里刚上传的文件
      const curfile = this.filelist.find(item => item.uid === file.uid)
      // 设置图片上传状态为加载
      curfile.status = 'uploading'
      cos.putObject({
        Bucket: 'hrsass-152-1316175705', /* 填入您自己的存储桶，必须字段 */
        Region: 'ap-beijing', /* 存储桶所在地域，例如ap-beijing，必须字段 */
        Key: +new Date() + file.name, /* 存储在桶里的对象键，必须字段 用时间戳+图片的名字  防止重名 */
        Body: file, /* 必须，上传文件对象，可以是input[type="file"]标签选择本地文件后得到的file对象 */
        onProgress: function (progressData) { // 上传过程的函数
          // console.log(JSON.stringify(progressData))
          // 将上传的进度条设置为上传的progressData.percent  从0到1  再*100
          curfile.percentage = progressData.percent * 100
        }
      }, function (err, data) {
        // console.log(err || data)
        // 失败就弹框退出
        if (err) {
          this.$message.error('图片上传失败，请稍后再试')
          return
        }
        // 将上传的图片的地址转为网络存储桶的地址  //是为了获取到本网站的协议  自动匹配
        curfile.url = '//' + data.Location
        // 延时操作是为了更好地展示进度条
        setTimeout(() => {
          curfile.status = 'success'
        }, 500)
      })
    },
    /**
     * 文件状态改变
     */
    handleChange (file, filelist) {
      // 改变后的filelist展开，赋值给数据里的filelist
      this.filelist = [...filelist]
    },
    /**
     * 上传之前的校验
     * 配置上传前的校验, 只要通过校验, 才能进行上传
     */
    beforeUpload (file) {
      // 1. 限制文件类型 file.type
      const types = ['image/jpeg', 'image/gif', 'image/bmp', 'image/png']
      if (!types.includes(file.type)) {
        this.$message.error('上传的图片格式, 必须是jpg, gif, bmp, png的格式!')
        return false
      }
      // 2. 限制文件大小 file.size
      if (file.size / 1024 / 1024 >= 5) {
        this.$message.error('上传头像过大, 超过了5M, 必须5M以内')
        return false
      }
      return true
    }
  }
}
</script>
<style lang="scss" scoped>
.disabled {
  ::v-deep {
    .el-upload--picture-card {
      display: none
    }
  }
}

</style>
